// insert here for test
#include <list> 
#include <forward_list>
#include <ext/slist>
// insert end
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <string>
#include <algorithm>

// 确保内存被回收
#include <malloc.h> // malloc_trim

#include "test.h"
#include "print.hpp"

using std::cin;
using std::cout;
using std::endl;
using std::string;

using std::find;

// 双向循环链表
using std::list;
// 单链表
using std::forward_list;

const long STRING_LENGTH = 10;

// 测试双向循环链表
void test_list(const long& value) {
    print("\ntest_list() ....");

    // 创建一个双向循环链表
    list<string> c;

    // 用于测试的计时器
    TimeCounter t;

    // 插入数据
    for(long i=0; i<value; ++i) {
        c.push_back(get_a_random_string(STRING_LENGTH));
        // get_a_random_string 已经包含错误处理，此处忽略
    }
    t.endAndShow("insert use time(s): ");
    print("list.size(): ", c.size());
    print("list.max_size(): ", c.max_size());
    print("list.front(): ", c.front());
    print("list.back(): ", c.back());

    // 查找一个成员
    string target = get_a_target_string();
    t.start();
    auto pItem = find(c.begin(), c.end(), target);
    t.endAndShow("find use time(s): ");

    if (pItem != c.end()) {
        print("found: ", *pItem);
    } else {
        print("sorry, not found");
    }

    // 排序
    print("sorting ... ");
    print("list.sort()");
    t.start();
    c.sort();
    t.endAndShow("sort use time: ");
    // std::sort() 不可用，list 不能进行随机访问
}

void test_forward_list(const long& value) {
    print("\n test_forward_list() ...");

    forward_list<string> c;
    TimeCounter t;
    for (long i=0; i<value; ++i) {
        c.push_front(get_a_random_string(STRING_LENGTH));
    }
    t.endAndShow("insert use time(s): ");
    // print("forward_list.size(): ", c.size()); // 不存在 size() 结果
    print("forward_list.max_size(): ", c.max_size());
    print("forward_list.front(): ", c.front());

    // find
    print("find start");
    string target = get_a_target_string();
    t.start();
    auto pItem = find(c.begin(), c.end(), target);
    t.endAndShow("find use time: ");

    if (pItem != c.end()) {
        print("found: ", *pItem);
    } else {
        print("sorry, not found");
    }

    // sort
    print("sort start: ");
    t.start();
    c.sort();
    t.endAndShow("sort use time(): ");
}

// void test_slist(const long& value) {
//     print("\n test_slist() ... ");
//     __gnu_cxx::slist<string> c;
//     TimeCounter t;
//     for (long i=0; i<value; ++i) {
//         c.push_front(get_a_random_string(STRING_LENGTH));
//     }
//     t.endAndShow("insert use time: ");
// }

void menu() {
    cout << "Enter option: " << endl
        << "1: test_list;" << endl
        << "2: test_forward_list;" << endl
        // << "3: test_slist;" << endl
        << "q: end." << endl;
    cout << "Please input number for test program: " << endl;
}

int main(void) {
    print("start...");
    print("the size for test program");
    long value = get_a_target_long();
    char option;

    menu();
    while (cin >> option) {
        switch (option) {
            case '1':
                test_list(value);
                break;
            case '2':
                test_forward_list(value);
                break;
            // case '3':
                // test_slist(value);
                // break;
            case 'q':
                print("buy!");
                return 0;
            default:
                print("wrong option");
                return 0;
        }
        // 如果不回收，下次测试时间明显会增长
        malloc_trim(0);
        menu();
    }


    return 0;
}

